package com.file.system.controller.system;


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.file.system.entity.dict.DataRange;
import com.file.system.entity.res.BaseCode;
import com.file.system.entity.res.CommonResult;
import com.file.system.entity.res.DataPage;
import com.file.system.entity.system.*;
import com.file.system.service.system.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.hutool.core.util.ObjectUtil.isNotEmpty;


/**
 * 角色
 *
 * @author jch
 */
@RestController
@Validated
@RequestMapping("/web/role")
public class WebRoleController {

    @Autowired
    private IWebRoleService service;
    @Autowired
    private IWebRoleMenuService iWebRoleMenuService;
    @Autowired
    private IWebRoleUserService iWebRoleUserService;
    @Autowired
    private IWebRoleDataService iWebRoleDataService;
    @Autowired
    private IWebRoleNodeService iWebRoleNodeService;
    @Autowired
    private IWebMenuService iWebMenuService;

    /**
     * 查询角色分页
     *
     * @param pageIndex 页数
     * @param pageSize  每页条数
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/page/{pageIndex}/{pageSize}")
    public CommonResult<DataPage<List<WebRole>>> select(@PathVariable
                                                        @Min(value = 1, message = "页数最小1")
                                                        Integer pageIndex,
                                                        @PathVariable
                                                        @Min(value = 1, message = "每页条数最小1")
                                                        @Max(value = 100, message = "每页条数最大100")
                                                        Integer pageSize,
                                                        @RequestBody @Validated WebRole webRole
    ) {
        QueryWrapper<WebRole> query = new QueryWrapper<>();
        //排序
        query.orderByAsc("a.sort");
        //判断是否删除
        query.eq("a.is_del", 0);
        //判断是否为空，不为空则添加查询条件
        query.like(isNotEmpty(webRole.getName()), "a.name", webRole.getName());
        //判断是否为空，不为空则添加查询条件
        query.eq(isNotEmpty(webRole.getDictGroup()), "a.dict_group", webRole.getDictGroup());
        //判断是否为空，不为空则添加查询条件
        query.eq(isNotEmpty(webRole.getDictOnOff()), "a.dict_on_off", webRole.getDictOnOff());
        //判断是否为空，不为空则添加查询条件
        query.like(isNotEmpty(webRole.getCode()), "a.code", webRole.getCode());
        //查询集合
        DataPage<List<WebRole>> dp = service.page(pageIndex, pageSize, query);
        return CommonResult.ok().setResult(dp);
    }


    /**
     * 通过id查询角色
     *
     * @param id 角色id
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/id/{id}")
    public CommonResult<WebRole> selectById(@PathVariable
                                            @Min(value = 1, message = "id长度最小1")
                                            Long id) {
        //查询集合
        WebRole webRole = service.getById(id);
        if (Objects.isNull(webRole)) {
            return CommonResult.ok().setResult(webRole);
        }
        //查询菜单
        List<WebRoleMenu> list = iWebRoleMenuService.list(new QueryWrapper<WebRoleMenu>()
                .eq("a.fk_role_id", id)
        );
        //未分配菜单return
        if (list.size() < 1) {
            return CommonResult.ok().setResult(webRole);
        }
        List<Long> ids = list.stream().map(webRoleMenu -> webRoleMenu.getFkMenuId()).collect(Collectors.toList());
        //查询菜单
        List<WebMenu> menuList = iWebMenuService.list(new QueryWrapper<WebMenu>()
                .in("a.id", ids)
        );
        webRole.setMenuList(menuList);
        return CommonResult.ok().setResult(webRole);
    }

    /**
     * 通过ids查询角色集合
     *
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/listByIds")
    public CommonResult<List<WebRole>> listByIds(@RequestBody List<Long> ids) {
        //查询集合
        List<WebRole> list = service.listByIds(ids);
        return CommonResult.ok().setResult(list);
    }


    /**
     * 查询所有非删除状态角色
     *
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/listAll")
    public CommonResult<List<WebRole>> listAll() {
        //查询集合
        List<WebRole> list = service.listAll();
        return CommonResult.ok().setResult(list);
    }


    /**
     * 通过id删除角色
     *
     * @param id id
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/remove/{id}")
    public CommonResult removeById(@PathVariable
                                   @Min(value = 1, message = "id长度最小1")
                                   Long id) {
        //返回
        return CommonResult.check(service.removeById(id));
    }


    /**
     * 通过id编辑角色
     *
     * @param webRole 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/updateById")
    public CommonResult<WebRole> updateById(@RequestBody @Validated(WebRole.update.class) WebRole webRole) {
        WebRole webRoleOld = service.getById(webRole.getId());
        //检查编码是否存在
        if (ObjectUtil.notEqual(webRoleOld.getCode(), webRole.getCode())) {
            int count = service.count(new QueryWrapper<WebRole>()
                    .eq("a.is_del", "0")
                    .eq("a.code", webRole.getCode())
            );
            if (count > 0) return CommonResult.fail(BaseCode.Common.PARAM_CODE_EXIST).setResult(webRole);
        }
        //编辑修改
        boolean state = service.updateById(webRole);
        if (!state) {
            return CommonResult.fail().setText("编辑失败");
        }
        //删除旧菜单
        state = iWebRoleMenuService.removeMenuByRoleId(webRole.getId());
        if (!state) {
            return CommonResult.fail().setText("删除旧菜单失败");
        }
        if (!Objects.isNull(webRole.getMenuList())) {
            //重新分配添加菜单
            List<WebRoleMenu> list = new ArrayList<>();
            for (WebMenu menu : webRole.getMenuList()) {
                WebRoleMenu webRoleMenu = new WebRoleMenu();
                webRoleMenu.setId(IdUtil.getSnowflakeNextId());
                webRoleMenu.setFkMenuId(menu.getId());
                webRoleMenu.setFkRoleId(webRole.getId());
                list.add(webRoleMenu);
            }
            state = iWebRoleMenuService.saveBatch(list);
            if (!state) {
                return CommonResult.fail().setText("添加角色菜单失败");
            }
        }
        return CommonResult.ok().setResult(webRole);
    }


    /**
     * 添加角色
     *
     * @param webRole 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/save")
    public CommonResult<WebRole> save(@RequestBody @Validated(WebRole.add.class) WebRole webRole) {
        //检查角色编码是否已存在
        int count = service.count(new QueryWrapper<WebRole>()
                .eq("a.is_del", "0")
                .eq("a.code", webRole.getCode())
        );
        if (count > 0) return CommonResult.fail(BaseCode.Common.PARAM_CODE_EXIST).setResult(webRole);
        //添加角色
        boolean state = service.save(webRole);
        if (!state) {
            return CommonResult.fail().setResult(webRole).setText("添加角色失败");
        }
        if (!webRole.getMenuList().isEmpty()) {
            //添加角色菜单
            List<WebRoleMenu> list = new ArrayList<>();
            for (WebMenu menu : webRole.getMenuList()) {
                WebRoleMenu webRoleMenu = new WebRoleMenu();
                webRoleMenu.setId(IdUtil.getSnowflakeNextId());
                webRoleMenu.setFkMenuId(menu.getId());
                webRoleMenu.setFkRoleId(webRole.getId());
                list.add(webRoleMenu);
            }
            state = iWebRoleMenuService.saveBatch(list);
            if (!state) {
                return CommonResult.fail().setText("添加角色菜单失败");
            }
        }
        return CommonResult.check(state).setResult(webRole);
    }


    /**
     * 授权用户
     *
     * @param webRole 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/save/user")
    public CommonResult saveUser(@RequestBody @Validated(WebRole.addUser.class) WebRole webRole) {
        List<WebRoleUser> list = new ArrayList<>();
        //删除旧关联
        for (WebUser user : webRole.getUserList()) {
            //通过角色ID用户ID删除关联
            boolean state = iWebRoleUserService.removeByRoleAndUser(webRole.getId(), user.getId());
            if (!state) {
                return CommonResult.fail().setText("删除授权用户失败");
            }
            //设置新关联
            WebRoleUser webRoleUser = new WebRoleUser();
            webRoleUser.setId(IdUtil.getSnowflakeNextId());
            webRoleUser.setFkRoleId(webRole.getId());
            webRoleUser.setFkUserId(user.getId());
            list.add(webRoleUser);
        }
        boolean state = iWebRoleUserService.saveBatch(list);
        if (!state) {
            return CommonResult.fail().setText("授权用户用户失败");
        }

        return CommonResult.ok();
    }


    /**
     * 取消授权用户
     *
     * @param webRole 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/remove/user")
    public CommonResult removeUser(@RequestBody @Validated(WebRole.addUser.class) WebRole webRole) {
        //删除旧关联
        for (WebUser user : webRole.getUserList()) {
            //通过角色ID用户ID删除关联
            boolean state = iWebRoleUserService.removeByRoleAndUser(webRole.getId(), user.getId());
            if (!state) {
                return CommonResult.fail().setText("取消授权失败");
            }
        }
        return CommonResult.ok();
    }


    /**
     * 通过角色ID查询账号
     *
     * @param webUser 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/user/{pageIndex}/{pageSize}")
    public CommonResult<DataPage<List<WebUser>>> roleUser(@PathVariable
                                                          @Min(value = 1, message = "页数最小1")
                                                          Integer pageIndex,
                                                          @PathVariable
                                                          @Min(value = 1, message = "每页条数最小1")
                                                          @Max(value = 100, message = "每页条数最大100")
                                                          Integer pageSize,
                                                          @RequestBody @Validated WebUser webUser) {

        QueryWrapper<WebUser> query = new QueryWrapper<>();
        // 根据id降序排列
        query.orderByDesc("a.id");
        // 判断是否删除
        query.eq("a.is_del", 0);
        // 判断角色id
        query.eq("b.fk_role_id", webUser.getFkRoleId());
        // 判断是否为空，不为空则添加模糊查询条件
        query.like(isNotEmpty(webUser.getName()), "a.name", webUser.getName());
        query.like(isNotEmpty(webUser.getUsername()), "a.username", webUser.getUsername());
        query.like(isNotEmpty(webUser.getPhone()), "a.phone", webUser.getPhone());
        query.like(isNotEmpty(webUser.getEmail()), "a.email", webUser.getEmail());
        // 判断是否为空，不为空则添加查询条件
        query.eq(isNotEmpty(webUser.getDictOnOff()), "a.dict_on_off", webUser.getDictOnOff());
        //通过角色ID查询该角色下的账号
        DataPage<List<WebUser>> dp = iWebRoleUserService.selectRoleUserByPage(pageIndex, pageSize, query);
        return CommonResult.ok().setResult(dp);
    }


    /**
     * 分配数据权限
     *
     * @param webRoleData 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/data/save")
    public CommonResult dataSave(@RequestBody @Validated(WebRoleData.update.class) WebRoleData webRoleData) {
        //判断数据权限是否存在，不存在新增
        WebRoleData temp = iWebRoleDataService.getOne(new QueryWrapper<WebRoleData>()
                .eq("a.is_del", 0)
                .eq("a.code", webRoleData.getCode())
                .eq("a.fk_role_id", webRoleData.getFkRoleId())
        );

        //新增或修改数据权限
        if (ObjectUtil.isNull(temp)) {
            boolean state = iWebRoleDataService.save(webRoleData);
            if (!state) {
                return CommonResult.fail().setText("添加数据权限失败");
            }
        } else {
            //删除旧数据权限节点
            boolean state = iWebRoleNodeService.removeByRoleAndCode(temp.getCode(), webRoleData.getFkRoleId());
            if (!state) {
                return CommonResult.fail().setText("删除节点数据失败");
            }

            //更新数据权限
            temp.setDictDataRange(webRoleData.getDictDataRange());
            temp.setFkRoleId(webRoleData.getFkRoleId());
            state = iWebRoleDataService.updateById(temp);
            if (!state) {
                return CommonResult.fail().setText("编辑数据权限失败");
            }
        }

        //新增节点数据
        if (ObjectUtil.equal(webRoleData.getDictDataRange(), DataRange.CUSTOM.val) && !webRoleData.getNodeList().isEmpty()) {
            List<WebRoleNode> nodeList = webRoleData.getNodeList().stream()
                    .map(node -> {
                        WebRoleNode tempNode = new WebRoleNode();
                        tempNode.setId(IdUtil.getSnowflakeNextId());
                        tempNode.setCode(webRoleData.getCode());
                        tempNode.setFkRoleId(webRoleData.getFkRoleId());
                        tempNode.setFkNodeId(node.getFkNodeId());
                        return tempNode;
                    })
                    .collect(Collectors.toList());

            boolean state = iWebRoleNodeService.saveBatch(nodeList);
            if (!state) {
                return CommonResult.fail().setText("新增节点数据失败");
            }
        }
        return CommonResult.ok();
    }


    /**
     * 查询数据权限
     *
     * @param webRoleData 角色
     * @return CommonResult
     * @apiNote -
     * @author jch
     */
    @PostMapping("/data/get")
    public CommonResult<WebRoleData> dataGet(@RequestBody @Validated(WebRoleData.select.class) WebRoleData webRoleData) {
        //判断数据权限是否存在，不存在新增
        WebRoleData temp = iWebRoleDataService.getOne(new QueryWrapper<WebRoleData>()
                .eq("a.is_del", 0)
                .eq("a.code", webRoleData.getCode())
                .eq("a.fk_role_id", webRoleData.getFkRoleId())
        );
        if (ObjectUtil.isNull(temp)) {
            return CommonResult.ok().setResult(new ArrayList<>());
        }
        //自定义数据权限
        if (ObjectUtil.equal(temp.getDictDataRange(), DataRange.CUSTOM.val)) {
            List<WebRoleNode> list = iWebRoleNodeService.list(new QueryWrapper<WebRoleNode>()
                    .eq("a.code", webRoleData.getCode())
                    .eq("a.fk_role_id", webRoleData.getFkRoleId())
            );
            temp.setNodeList(list);
        }
        return CommonResult.ok().setResult(temp);
    }
}

